#include "CommFunc.h"
#include <openssl/md5.h>
#include <codecvt>
#include <fstream>
#include <unistd.h>
#include <stdio.h>
#include <execinfo.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <string>
#include <sstream>
#include<iterator>

using std::string;
using std::stringstream;
using std::istream_iterator;
using std::ostream_iterator;

std::wstring S2WS(const std::string& str) {
    std::wstring_convert < std::codecvt_utf8 < wchar_t >> conv;
    return conv.from_bytes(str);
}

std::string md5(const std::string& src) {
    unsigned char md[33] = { 0 };
    MD5((const unsigned char*) src.c_str(), src.length(), md);
    char buf[65] = { 0 };
    char tmp[3] = { 0 };

    for (int i = 0; i < 32; i++) {
        sprintf(tmp, "%02x", md[i]);
        strcat(buf, tmp);
    }

    buf[32] = '\0';
    return std::string(buf);
}

std::string get_ip() {
    std::ifstream in("/tmp/ip");
    std::ostringstream tmp;
    tmp << in.rdbuf();
    return tmp.str();
}

const char* find_base_address(const char* name) {
    static char BaseAddr[20];
    int pid = getpid();
    char file_name[50];
    sprintf(file_name, "/proc/%d/maps", pid);
    char cmd[100];
    sprintf(cmd, "grep %s %s | head -1 | awk -F- \'{print $1}\'", name, file_name);
    FILE* file = popen(cmd, "r");
    int n = fread(BaseAddr, 1, 20, file);
    BaseAddr[n - 1] = '\0';
    return BaseAddr;
}

bool base64_encode(const string& input, string* output) {
    if (input.empty()) {
        return true;
    }

    typedef boost::archive::iterators::base64_from_binary < boost::archive::iterators::transform_width < string::const_iterator, 6, 8 >> Base64EncodeIterator;
    stringstream result;
    copy(Base64EncodeIterator(input.begin()), Base64EncodeIterator(input.end()), ostream_iterator < char >(result));
    size_t equal_count = (3 - input.length() % 3) % 3;

    for (size_t i = 0; i < equal_count; i++) {
        result.put('=');
    }

    *output = result.str();
    return output->empty() == false;
}

bool base64_decode(const std::string& input, std::string* output) {
    typedef boost::archive::iterators::transform_width < boost::archive::iterators::binary_from_base64 < std::string::const_iterator >, 8, 6 > Base64DecodeIterator;
    std::stringstream result;

    try {
        copy(Base64DecodeIterator(input.begin()), Base64DecodeIterator(input.end()), ostream_iterator < char >(result));
    } catch (...) {
        return false;
    }

    *output = result.str();
    return output->empty() == false;
}

struct timeval getTime() {
    struct timeval time;
    gettimeofday(&time, NULL);
    return time;
}
